//#include "log.h"
#include "Thread.h"
#include <thread>
#include <iostream>
#include "platformSpecific.h"
#include <fcntl.h>
#include <cstring>
#include <sys/stat.h>
#include <chrono>


//using namespace std;


Thread::~Thread()
{
    //stop();
}

Thread::State Thread::state() const
{
    return _state;
}

void Thread::start()
{
    if (_thread == nullptr)
    {
        this->_thread = std::make_unique<std::thread>(&Thread::run, this);
        //_thread = new thread(&Thread::run, this);
        _pauseFlag = false;
        _stopFlag = false;
        _state = Running;
        std::stringstream ss;
        ss << std::this_thread::get_id();
        this->tid = ss.str();
    }
}

void Thread::stop()
{
    if (_thread != nullptr)
    {
        _pauseFlag = false;
        _stopFlag = true;
        _condition.notify_all();  // Notify one waiting thread, if there is one.
        _thread->join(); // wait for thread finished
        if (this->executeHandleBeforePause) {
            //this->log(DEBUG, this->name, ": ", this->tid, "execute beforeHandle;");
            this->beforeHandle();
        }
        this->_thread.reset();
        //delete _thread;
        _thread = nullptr;
        _state = Stoped;
    }
}

void Thread::pause()
{
    if (_thread != nullptr)
    {
        _pauseFlag = true;
        //        std::stringstream ss;
        //        ss<<this_thread::get_id();
        //        this->log(INFO,"Pause thread:",this->name," id:",ss.str());
    }
}

void Thread::resume()
{
    if (_thread != nullptr)
    {
        _pauseFlag = false;
        //        std::stringstream ss;
        //        ss<<this_thread::get_id();
        //        this->log(INFO,"Resume thread:",this->name," id:",ss.str());
        _condition.notify_all();
    }
}

void Thread::run()
{
    //this->log(INFO, "enter thread:", this->name, " id:", this->tid);
    std::cout << "enter thread:" << this->name<<",id:"<<this->tid << std::endl;

    while (!_stopFlag)
    {
        _state = Running;
        //this->log(DEBUG,this->name,": ",this->tid," prepare to execute process;");
        /*if (this->inMessageQ->hasData()) {
            std::string message = this->inMessageQ->get(true);
            this->setup(message);
        }*/
        process();
        if (_pauseFlag)
        {
            std::unique_lock<std::mutex> locker(_mutex);
            _state = Paused;
            while (_pauseFlag)
            {
                _condition.wait(locker); // Unlock _mutex and wait to be notified
            }
            locker.unlock();
        }
        if (this->needYield) {
            std::this_thread::yield();
        }
    }
    _pauseFlag = false;
    _stopFlag = false;
    //this->log(INFO, "exit thread:", this->name, " id:", this->tid);
}

void Thread::sleep(int& s)
{
    std::this_thread::sleep_for(std::chrono::duration<double>(s));
}